//------------------------------------------------------------------------------
///
///	\file sm.h
///
///	\brief
///	State machine declaration file
///
//	$Id: sm.h 319 2015-01-19 20:17:56Z ac.verbeck@gmail.com $
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//	The MIT License (MIT)
//
//	Copyright (c) 2014 A.C. Verbeck
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.

//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//	THE SOFTWARE.
//------------------------------------------------------------------------------
#pragma once

//------------------------------------------------------------------------------
//  Typedef variables for state machine
//------------------------------------------------------------------------------
typedef uint32_t	SM_EVENT;													///<	Events passed to state machine
typedef uint16_t	SM_STATE;													///<	Current state
typedef enum {
	SM_OK		= 0x0000,														///<	State machine is running well
	SM_ERROR	= 0x0100,														///<	State machine error
	SM_SC_ERROR	= 0x0101														///<	State machine state count error
} SM_STATUS;																	///<	Current status of the state machine

//------------------------------------------------------------------------------
//  Define SM control events
//------------------------------------------------------------------------------
enum {
	SM_INIT		= 0x0200,
	SM_ENTER	= 0x0201,
	SM_EXIT		= 0x0202,
};

//------------------------------------------------------------------------------
//  Forward reference so that STATE_FN can be declared
//------------------------------------------------------------------------------
typedef struct STATE_MACHINEtag STATE_MACHINE;									//  Forward reference

//------------------------------------------------------------------------------
//  Typedef functions for state machine
//------------------------------------------------------------------------------
typedef SM_STATUS	(*STATE_FN)(STATE_MACHINE* sm, SM_EVENT ev);				//	State processing function
typedef SM_STATE	(*STATE_INIT)(STATE_MACHINE* sm);							//	Init function

//------------------------------------------------------------------------------
//  Typedef structures for state machine
//------------------------------------------------------------------------------
typedef struct SM_STAT_FNEtag {
	STATE_FN	Enter;															///<	Enter function
	STATE_FN	Process;														///<	Processing function
	STATE_FN	Exit;															///<	Exit function
} SM_STATE_FN;

struct STATE_MACHINEtag {
	SM_STATE	CurrState;														///<	SM state
	SM_STATE	NewState;														///<	SM next state
	SM_STATE	PrevState;														///<	SM last state
	SM_STATUS	Status;															///<	SM status
	STATE_INIT	InitFn;															///<	SM initial function
	bool		StateChange;													///<	Change state
	uint8_t		MaxState;														///<	Max size of state array: so we don't go off the end!
	uint8_t		x,y;															///<	Size of the auto array
};

//------------------------------------------------------------------------------
//  Function declaration
//------------------------------------------------------------------------------
SM_STATUS	SM_Init(STATE_MACHINE* sm, const SM_STATE_FN st[], uint32_t ms);
SM_STATUS	SM_Process(STATE_MACHINE* sm, const SM_STATE_FN st[], SM_EVENT ev);
SM_STATUS	SM_StateChange(STATE_MACHINE* sm, SM_STATE st);
SM_STATUS	SM_StateAuto(STATE_MACHINE* sm, const SM_STATE sa[sm->x][sm->y], SM_EVENT ev);
SM_STATUS	SM_StateNext(STATE_MACHINE* sm, SM_STATE const sa[]);
SM_STATUS	SM_StatePrev(STATE_MACHINE* sm);

SM_STATE	SM_GetState(STATE_MACHINE* sm);
SM_STATUS	SM_GetStatus(STATE_MACHINE* sm);

//
//	End: sm.h
//
